#include "windowutil.h"

#include <QApplication>
// #include <QDesktopWidget>
#include <QScreen>
#include <QWindow>
#include <QPalette>
#include <QStyle>
#include <QStyleFactory>

#ifdef Q_OS_WIN
#include <windows.h>
#include <dwmapi.h>
#endif

#ifdef Q_OS_LINUX
#include <QtX11Extras/QX11Info>
#include <X11/Xlib.h>
#endif

void WindowUtil::setFramelessWithShadow(QWidget *window, int shadowRadius)
{
	if (!window)	return;

	// 无边框
	window->setWindowFlags(window->windowFlags() | Qt::FramelessWindowHint);
	window->setAttribute(Qt::WA_TranslucentBackground);

	// 跨平台不同的阴影实现
	#ifdef Q_OS_WIN
    setWindowsShadow(window, shadowRadius);
	#elif Q_OS_LINUX
    setLinuxShadow(window, shadowRadius);
	#endif
}

void WindowUtil::setTopMost(QWidget *window, bool topMost)
{
	if (!window)	return;
	if (topMost)	window->setWindowFlags(window->windowFlags() | Qt::FramelessWindowHint);
	else			window->setWindowFlags(window->windowFlags() & ~Qt::FramelessWindowHint);
	window->show();
}

void WindowUtil::moveWindowBelow(QWidget *window, QWidget *targetWindow)
{
	if (!window || !targetWindow)	return;
	// caculate pos
	QPoint targetPos = targetWindow->mapToGlobal(QPoint(0, 0));
	int x = targetPos.x();
	int y = targetPos.y() + targetWindow->height();

	// 不超出屏幕
	QScreen *screen = QGuiApplication::screenAt(window->geometry().center());
	QRect screenRect = screen ? screen->availableGeometry() : QGuiApplication::primaryScreen()->availableGeometry();
	if (y + window->height() > screenRect.bottom()) 	y = targetPos.y() - window->height();
	if (x + window->width() > screenRect.right()) 	x = screenRect.right() - window->width();

	window->move(x, y);
}

void WindowUtil::moveToScreenCenter(QWidget *window)
{
	if (!window) return;
	QScreen *screen = QGuiApplication::screenAt(window->geometry().center());
	QRect screenRect = screen ? screen->availableGeometry() : QGuiApplication::primaryScreen()->availableGeometry();
	window->move(screenRect.center() - window->rect().center());
}

void WindowUtil::adaptPlatformStyle(QWidget *window)
{
	if (!window) return;
	#ifdef Q_OS_WIN
    window->setStyle(QStyleFactory::create("Fusion"));
	#elif Q_OS_LINUX
    window->setStyle(QStyleFactory::create("Breeze"));
	#endif
	adjustToSystemTheme(window);
}

void WindowUtil::adjustToSystemTheme(QWidget *window)
{
	if (!window) return;

	// get system Theme
	QPalette palette = window->palette();
	QColor windowColor = palette.color(QPalette::Window);

	bool isDarkTheme = (windowColor.lightness() < 128);

	// 不同色系下的调整
	if (isDarkTheme) {
		QColor textColor = palette.color(QPalette::Text);
		int h, s, l, a;
		textColor.getHsl(&h, &s, &l, &a);
		textColor.setHsl(h, s, 200, a); // 使文本更亮
		palette.setColor(QPalette::Text, textColor);
	} else {
		// 浅色主题调整
        QColor textColor = palette.color(QPalette::Text);
        int h, s, l, a;
		textColor.getHsl(&h, &s, &l, &a);
		textColor.setHsl(h, s, 50, a); // 使文本更亮
		palette.setColor(QPalette::Text, textColor);
	}
	window->setPalette(palette);
}

QWidget *WindowUtil::getActiveWindow()
{
	return QApplication::activeWindow();
}

#ifdef Q_OS_WIN
void WindowUtil::setWindowsShadow(QWidget *window, int shadowRadius)
{
	if (!window) return;
	HWND hwnd = (HWND)window->winId();	
	DWORD style = GetWindowLong(hwnd, GWL_STYLE);

	// 阴影
	const MARGINS shadowMargins = {shadowRadius, shadowRadius, shadowRadius, shadowRadius};
    DwmExtendFrameIntoClientArea(hwnd, &shadowMargins);
}
#endif

#ifdef Q_OS_LINUX
void WindowUtil::setLinuxShadow(QWidget *window, int shadowRadius)
{
    if (!window || !QX11Info::isPlatformX11() || shadowRadius < 0) {
        return; // 入参校验增强，避免无效操作
    }

    // 确保窗口已显示（未显示的窗口无法正确设置阴影）
    if (!window->isVisible()) {
        // 延迟到窗口显示后再设置阴影
        QObject::connect(window, &QWidget::shown, window, [window, shadowRadius]() {
            setLinuxShadow(window, shadowRadius);
        }, Qt::SingleShotConnection);
        return;
    }

    Display *display = QX11Info::display();
    Window winId = window->winId();
    if (!display || winId == None) {
        return;
    }

    // 基础阴影属性设置（兼容支持 _NET_WM_SHADOW 的窗口管理器）
    Atom netWMShadow = XInternAtom(display, "_NET_WM_SHADOW", false);
    if (netWMShadow != None) {
        // 阴影参数：根据半径计算阴影范围（扩展窗口边界）
        const int shadowOffset = qMax(1, shadowRadius / 4); // 阴影偏移量
        const int shadowExtent = shadowRadius + shadowOffset;

        // 构造阴影几何信息（x,y,宽度,高度,圆角半径）
        // 格式参考 freedesktop 扩展规范，这里使用简化的阴影窗口配置
        QVector<long> shadowData = {
            -shadowOffset, -shadowOffset,  // 阴影相对于窗口的偏移（左上）
            window->width() + 2 * shadowExtent,  // 阴影宽度
            window->height() + 2 * shadowExtent, // 阴影高度
            shadowRadius                   // 圆角半径（与阴影半径匹配）
        };

        // 设置阴影属性
        XChangeProperty(
            display,
            winId,
            netWMShadow,
            XA_CARDINAL,
            32,
            PropModeReplace,
            (const unsigned char *)shadowData.data(),
            shadowData.size()
        );
    }

    // 兼容不支持 _NET_WM_SHADOW 的窗口管理器：手动绘制阴影
    // 创建阴影容器（作为主窗口的子窗口，随主窗口移动）
    QWidget *shadowWidget = new QWidget(window);
    shadowWidget->setAttribute(Qt::WA_TransparentForMouseEvents); // 穿透鼠标事件
    shadowWidget->setAttribute(Qt::WA_NoChildEventsForParent);    // 不干扰主窗口事件
    shadowWidget->setStyleSheet(QString(
        "background-color: rgba(0, 0, 0, %1);"
        "border-radius: %2px;"
    ).arg(0.2).arg(shadowRadius)); // 半透明黑色 + 圆角匹配阴影半径

    // 计算阴影位置和大小（比主窗口大一圈，偏移显示）
    const int shadowMargin = shadowRadius;
    shadowWidget->setGeometry(
        -shadowMargin,
        -shadowMargin,
        window->width() + 2 * shadowMargin,
        window->height() + 2 * shadowMargin
    );

    // 随主窗口大小变化更新阴影
    QObject::connect(window, &QWidget::resizeEvent, [window, shadowWidget, shadowMargin](QResizeEvent *event) {
        shadowWidget->setGeometry(
            -shadowMargin,
            -shadowMargin,
            window->width() + 2 * shadowMargin,
            window->height() + 2 * shadowMargin
        );
        event->ignore();
    });

    // 确保阴影在最底层
    shadowWidget->lower();
    shadowWidget->show();

    XFlush(display);
}
#endif